#include "parse.h"
#include "simulate.h"
#include "solver.h"
#include "alg.h"
#include "timing.h"
#include "place.h"
#include "node.h"
#include <sstream>

#ifndef HUESEL2
#define HUESEL2
#endif

//#ifndef WRITERESMAP
//#define WRITERESMAP
//#endif

Circuit *C;
int MC_NUM;
int HeuTry;
int trace_size;
int ext_logic_level;
int assign_file_id;
double my_lambda;
vector<int> sim_vals;
//extern bool formHybrid();

double criteria = 0.7;
int main(int argc, char **argv)
{
        int seed1,seed2;
	char *filename, *placename;
	cout<<"parsing file............."<<endl;
	if (argc < 5) {
		cerr << "Usage: " << argv[0] << " bench_file" << " trace_size" << " seed1 seed2" <<endl;
		return 2;
	}
	else if (argc == 5) {
		filename = argv[1];
                trace_size = atoi(argv[2]);
                assign_file_id = atoi(argv[3]);
                ext_logic_level = atoi(argv[4]);
		//seed1 = atoi(argv[3]);
		//seed2 = atoi(argv[4]);
                my_lambda = atof(argv[4]);
	}
        else
        {
                cout<<"Wrong, retry!"<<endl;
                exit(1);
        }
        
        cout << "Size of an __uint128_t is " << sizeof(__uint128_t) << endl;
        cout << "Size of an unsigned long is " << sizeof(BIT_TYPE) << endl;
	parse(filename);
        
        //note that the value of HeuTry was set to 2 for collecting the
        //results of the proposal
        //HeuTry = trace_size;
        HeuTry = 4;
        if(trace_size == 0)
        {
                cout<<"Cannot select nothing! Try again..."<<endl;
                exit(0);
        }
        
        for(int i=0; i<C->signalSize(); ++i)
                C->getSignal(i)->setIndex(i);
        
	for(int i=0; i<C->gateSize(); ++i)
                C->getGate(i)->setGateIndex(i);
        
        //cout << "flipflop size is " << C->flipflopSize() << endl;
        for(int i=0; i<C->flipflopSize(); ++i)
                ((FlipflopNode*)(C->getFlipflop(i)))->FF_index = i;
        /*
        cout << "Input a flipflop's output name" << endl;
        while(1){
                string tmp;
                cin >> tmp;
                
                if(tmp == "Quit")
                        break;
                                
                cout << "flipflop " << tmp;
                for(int i=0; i<C->flipflopSize(); ++i){
                        if(C->getFlipflop(i)->getOutput(0)->getName() == tmp){
                                cout << " corresponds to " << i << endl;
                                break;
                        }
                }
        }        
        exit(0);
        */
	cout<<"probablity computation......"<<endl;
	Simulate *sim = new Simulate(C);

        string tmp = filename;
	tmp += ".resMap";
        char *s = new char[strlen(tmp.c_str())];
        strcpy(s,tmp.c_str());
        
        MC_NUM = 64;
        sim->trace_depth = MC_NUM;
        
        tmp = filename;
        //sim->SimInitDFFValue_ITC(tmp);
        //sim->resMapAnalysis(tmp);
        //tmp += "_report";//need this
        //return 0;
        
#ifndef HUESEL2
        
#ifdef WRITERESMAP
        ofstream out;
        cout<<tmp<<endl;
        //always open a clean and empty file
        out.open(s, ofstream::trunc);
        out.close();
        
        for(int i=0; i<C->flipflopSize(); ++i)
        {
                sim->clearTraced();
                C->getFlipflop(i)->getOutput(0)->setTraced(true);
                sim->addTraced(C->getFlipflop(i)->getOutput(0));
                cout<<"Flip flop "<< i <<"'s visibility is "<<sim->computVN(s)<<endl;
                C->getFlipflop(i)->getOutput(0)->setTraced(false);
        }
#endif        	
        sim->hueristicSelect(s, trace_size);        
#else
        cout << "observation window depth is " << TRACE_DEPTH_NUM * 8 * sizeof(BIT_TYPE) << endl;
        
        string tmp1 = filename;
	tmp1 += ".prob";
        
        if(assign_file_id != -1){
                tmp1 = filename;
                tmp1 += ".prob";
                stringstream ss;
                ss << assign_file_id;
                tmp1 += "_" + ss.str(); 
        }
        
        cout << "Prob file name is " << tmp1 << endl;
        C->read_prob(&tmp1[0]);
        
        double lampda = 0.0;
        std::pair<double, double> SRR_GRR;
        //cout<< "The Final total visibility is " <<sim->simSelectValeria(trace_size, tmp.c_str()) << endl;
        //cout<< "The Final total visibility is " <<sim->simSelect(trace_size,tmp.c_str())<<endl;
	//sim->hueristicSelect2(trace_size, tmp.c_str());//this is the function that contains our heuristics
        //SRR_GRR = sim->simSelect(trace_size,tmp.c_str());
        //SRR_GRR = sim->biasedSelect(trace_size, tmp.c_str(), lampda);
        //SRR_GRR = sim->multimodeRef2Select(trace_size, tmp.c_str());
        //SRR_GRR = sim->multimodeSelect(trace_size, tmp.c_str());
        //SRR_GRR = sim->multimodeSimulateAnealing(trace_size, tmp.c_str());
        //SRR_GRR = sim->multimodeSASingleMode(trace_size, tmp.c_str());
        
        //SRR_GRR = sim->singleModeForwardGreedy(trace_size, tmp.c_str());
        double SRR = sim->SW_EXPR_Trace_Selection(trace_size, tmp.c_str());//RATS
        
        //SRR_GRR = sim->multimodeMergeSelect(trace_size, tmp.c_str());
        //SRR_GRR = sim->multimodeRef2MergeSelect(trace_size, tmp.c_str());
        //SRR_GRR = sim->multimodeSimulateAnealingMerge(trace_size, tmp.c_str());
        //cout << endl;
        
        /*------------------------------Hamid's approach begins----------------------------------*/
        /*
        Place *pl = new Place(C);
        Algorithm *alg = new Algorithm(C, pl, 0);  
        alg->test_r = false;
        cout<<"selecting trace signals............."<<endl;
        
        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_ILP_hamid";
        stringstream ss1;
        ss1 << assign_file_id;
        if(assign_file_id != -1)
                str += ss1.str();
        cout << "trace check file name is " << str << endl;
        
        clock_t start, finish;
        start = clock();
        alg->traceSelect(trace_size); //trace selection
        finish = clock();
        cout<<"Total trace selection time: " << ((finish - start) / CLOCKS_PER_SEC) << endl;
        
        
        ofstream out(str.c_str());
        cout << "selected traces are " << endl;
        out << alg->tracedSize() << endl;
        for(int i = 0; i < alg->tracedSize(); ++i){
                cout << alg->getTraced(i)->getName() << endl;
                out << alg->getTraced(i)->getName() << endl;
        }
        out << "!" << endl;
        out << "&&&";
        out.close();
        
        sim->Check_Traces_SRR_GRR(filename);
        */
        /*-------------------------------Hamid's approach ends----------------------------------*/
        
        /*
        //--------------------------------------Min 03/07/2013-----------------------------------
        struct timeval start1, finish1;
        gettimeofday(&start1, NULL);
        
        vector<TresMap*>* Mymap;
        vector<int> selected_traces;
        Solver* solver = new Solver;
        
        const bool batch = false;
        const bool writeToFile = true;
        if(batch == true){
                assert(assign_file_id != 0);
                //if(assign_file_id >= 0){
                Mymap = new vector<TresMap*>[assign_file_id];
                //sim->readResMap(filename, Mymap, true, -1);
                //Mymap = new vector<TresMap*>[1];
                sim->multimodeResMapGen(filename, Mymap, batch, writeToFile);
                //solver->read_resMap(1, C->flipflopSize(), Mymap);
                exit(0);
                //solver->read_resMap(assign_file_id, C->flipflopSize(), Mymap);
        }
        else{
                Mymap = new vector<TresMap*>[1];
                sim->multimodeResMapGen(filename, Mymap, batch, writeToFile);
                exit(0);
                //solver->read_resMap(1, C->flipflopSize(), Mymap);
        }
        
        solver->solver(trace_size, selected_traces);
        gettimeofday(&finish1, NULL);       
        cout<< "total runtime for solving ILP is: "
            << (finish1.tv_sec+(finish1.tv_usec/1000000.0) - start1.tv_sec+(start1.tv_usec/1000000.0)) << endl;

        string str = filename;
        str.erase(str.begin() + str.find("bench"), str.end());
        str += "trace_check_ILP0";
        ofstream out(str.c_str());
        out << selected_traces.size() << endl;
        for(int i = 0; i < selected_traces.size(); i++){
                cout << C->getFlipflop(selected_traces[i])->getOutput(0)->getName() << endl;
                out << C->getFlipflop(selected_traces[i])->getOutput(0)->getName() << endl;
        }
        out << "!" << endl;
        out << "&&&";
        out.close();
        //--------------------------------------Min 03/07/2013-----------------------------------
        */
        //sim->hueristicSelect3(trace_size,tmp.c_str());        
        //string benchname = filename;
        //sim->Check_Traces(trace_size, benchname);
        //sim->Check_Traces_SRR_GRR(benchname);
        //sim->Check_Traces(trace_size);
        //cout << "Final optimal SRR is " << SRR_GRR.first << "\t";
        //cout << "Final optimal GRR is " << SRR_GRR.second << endl;
        
#endif
                
        cout<<"Hueristic select ends............"<<endl;        
        return 0;
}
